package com.small.flowable.modules.app.controllers;


import com.common.basis.exception.BusinessException;
import com.common.basis.result.Result;
import com.common.basis.result.ResultSet;
import com.small.flowable.modules.app.dto.rsp.ModelRsp;
import com.small.flowable.modules.app.dto.rsp.ProcessDefinitionRsp;
import com.small.flowable.modules.app.services.ProcessDefinitionService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;


/**
 * 流程定义管理
 *
 * @author wangguochao
 */
@RequestMapping("process/definition")
@RestController
@AllArgsConstructor
@Slf4j
public class ProcessDefinitionController {

    private final ProcessDefinitionService processDefinitionService;
    private final ModelService modelService;
    private final RepositoryService repositoryService;

    /**
     * 根据ID部署流程
     *
     * @param modelId 流程模型ID
     * @return a57c5ea9-5957-11eb-bc22-acde48001122
     */
    @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
    @GetMapping("deploymentProcessDefinitionFromUIModelId")
    protected Result<String> deploymentProcessDefinitionFromUIModelId(String modelId) {
        try {
            Model model = modelService.getModel(modelId);
            BpmnModel bpmnModel = modelService.getBpmnModel(model);
            Deployment deployment = repositoryService.createDeployment()
                    .name(model.getName())
                    .addBpmnModel(model.getKey() + ".bpmn", bpmnModel).deploy();
            return ResultSet.go(deployment.getId());
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }


    /**
     * 已部署流程定义
     */
    @GetMapping("active/list")
    public Result<?> getActiveProcessList() {
        List<ProcessDefinitionRsp> records = processDefinitionService.getProcessDefinitions();
        return ResultSet.go(records);
    }

    /**
     * 部署实例历史
     *
     * @param processDefinitionKey key
     * @return 历史
     */
    @GetMapping("active/list/history")
    public Result<?> getProcessDefinitionsHistory(@RequestParam String processDefinitionKey) {
        List<ProcessDefinitionRsp> records = processDefinitionService.getProcessDefinitionsHistory(processDefinitionKey);
        return ResultSet.go(records);
    }

    /**
     * 流程设计器中保存的模型列表
     */
    @GetMapping("modeler/model/list")
    public Result<List<ModelRsp>> getModelList(@RequestParam String key, @RequestParam Integer modelType) {
        List<ModelRsp> records = processDefinitionService.getModelList(key, modelType);
        return ResultSet.go(records);
    }

    /**
     * 从流程设计器获取bpmn20.xml
     **/
    @GetMapping("/modeler/{modelId}/bpmn20")
    public void getBpmn20Xml(@PathVariable String modelId, HttpServletResponse response) throws IOException {
        String xml = processDefinitionService.getBPMNXmlFromModelId(modelId);
        if (!StringUtils.isEmpty(xml)) {
            response.setCharacterEncoding("utf-8");
            response.getWriter().write(xml);
            response.getWriter().close();
        }
    }

    /**
     * 部署流程设计器中流程
     **/
    @PostMapping("modeler/develop/")
    public Result<?> developFromModeler(
            @RequestParam String modelerId,
            @RequestParam String processDefinitionName) {
        processDefinitionService.developFromModeler(modelerId, processDefinitionName);
        return ResultSet.success();
    }

    /**
     * 获取图片
     *
     * @param diagramResourceName 图片资源名称
     * @param deploymentId        部署ID
     * @throws IOException io异常
     */
    @GetMapping("getImg")
    public void getImg(HttpServletResponse httpServletResponse,
                       @RequestParam String diagramResourceName,
                       @RequestParam String deploymentId) throws IOException {
        InputStream in = repositoryService.getResourceAsStream(deploymentId, diagramResourceName);
        StreamUtils.copy(in,httpServletResponse.getOutputStream());
    }
}
